// x除以的位置信息
export const xLocation = 2;
// subtitle, y轴的偏移尺度
export const subtitleHeightratio = 1.35;
// 主标题的y轴位置
export const titleHeightratio = 10;
// 副标题的y轴位置
export const textSubtitleHeight = 6;
// 副标题根据主标题的换行次数, 每次换行所偏移的位置
export const yOffset = 40;
// 手机的宽度和高度
export const phoneWidth = 360;
export const phoneHeight = 640;
// 最多可以创建多少个视频组
export const templateListLength = 20;
// 全局轻提示
import { message } from "ant-design-vue";
import { ref, reactive, computed } from "vue";

import store from "@/store/index.js";

import dayjs from "dayjs";
import { nanoid } from "nanoid";

import request from "@/common/utils/request";
import { nextTick } from "vue";

// 混剪数据处理
export * from "./template.js";

// 富文本处理方法
export * from "@/common/utils/richTextProcessing.js";

// 字幕配音 操作项数据
export const editor_operation_arr = [
  {
    id: 1,
    icon: "icon-shijian",
    visible: false,
    disabled: false,
    name: "插入停顿",
    tooltipText: "",
    Bo_visible: false,
    TimeData: [
      {
        label: "0.5s(短)",
        value: 0.5,
      },
      {
        label: "1s(中)",
        value: 1,
      },
      {
        label: "2s(长)",
        value: 2,
      },
    ],
    // tooltipText: "选择一个位置插入停顿",
  },
  {
    id: 2,
    icon: "icon-jingyin",
    visible: false,
    disabled: true,
    name: "取消诵读",
    Bo_visible: false,
    // tooltipText: "当前功能正在开发中",
    tooltipText: "先选中内容，再点击取消诵读",
  },
  {
    id: 3,
    icon: "icon-shuzi",
    visible: false,
    disabled: false,
    name: "数字读音",
    Bo_visible: false,
    // tooltipText: "当前功能正在开发中",
    tooltipText: "先选中数字，再进行发音调整",
    TimeData: [
      {
        label: "数字读法 (一百二十三万 一千两百三十四)",
        value: "cardinal",
      },
      {
        label: "序列读法(一二三一二三四)",
        value: "digits",
      },
      {
        label: "电话读法(幺二三 幺二三四)",
        value: "telephone",
      },
    ],
  },
  {
    id: 4,
    icon: "icon-shengkongqiehuan",
    visible: false,
    disabled: false,
    name: "修改发音",
    Bo_visible: false,
    // tooltipText: "当前功能正在开发中",
    tooltipText: "选中单一文字，点击修改发音",
  },
];

/**
 * 对齐方式
 */
export const alignmentArr = [
  {
    id: 1,
    type: "left",
    icon: "icon-zuoduiqi",
  },
  {
    id: 2,
    type: "center",
    icon: "icon-juzhongduiqi",
  },
  {
    id: 3,
    type: "right",
    icon: "icon-youduiqi",
  },
];

/**
 * 花字 img src
 */

export const fontImgSrc =
  "https://muse.console.volcengine.com/api/storage/objects/media/7259498746524991529_origin.png?infer_mime=ext&x-muse-token=ChYIARABGJzjjbAGIJyGk7AGKgQxNDA0EqYBCg4IqYCJuN%2By6vdlEOSFBBINCgt2b2xjX2VuZ2luZRoCGAIiCAoCaGwSAmNuKgYI2jQQhgMyKQoneyJiaXpfaWQiOiIxMDAwMDAwMDEiLCJkZXJpdmVkX3VpZCI6IiJ9QhQKEmljYXJjaC5pYW0uYXV0aHJwY0ouL2FwaS9zdG9yYWdlL29iamVjdHMvbWVkaWEvNzI1OTQ5ODc0NjUyNDk5MTUyORrYAnBYaWk0WVRhV0hKZnJNaWI2bDFzYyt5czRtMGx5UTUxL29FTW5MWnFIbDdKNStKSlljSTBFRWljbjk4ZFF2aUZwZGVlNjIwU04wQkg2bDZlbzQzSzR1NDlqQk5GOHhURjZGdFJKMTRzelpIK1lDZlZzbnlyem5iNktJMllQZWtKUnZNbmE2YlZZbUFrNHdmcXNkR0plZXNNTUdYb2pBb3lCa1V1cjVCK3BscmNzWUtPbVBaQ3Zma2VMU3VBRDRRcFdhODFvRUFPQXJzYVpYRlA0UnhyWGNrL3dDNjdiR1BpQWw2eXg3SE9OVzR3K0R5Q0ZMbFJBcDBQdEpzbCtQSVhKK2RMRHJFVFhzeE1YS05ITExWNGtvQmlFZDVKeHR3Y1dxbStoZGJzN0dDWXJISkxGYm1Ec2JhcDFrbXlPUi9lOEZPVitmZnpYTm0wdlQ4SUM2S3EyUT09";

/**
 * 切换光标函数
 * @param {id: 获取元素的id 或者自定义属性, collapse: 换行后光标移到开始还是结尾 true为开始, false为结尾}
 */

export const changeFocus = (id, collapse = true) => {
  const focusDom = document.querySelector(id);
  const range = document.createRange();
  const selection = window.getSelection();
  // 将范围的起止点都设置到新元素的末尾
  range.selectNodeContents(focusDom);
  range.collapse(collapse); // false 代表范围折叠到末端
  // 清除当前的选择，并添加新的范围
  selection.removeAllRanges();
  selection.addRange(range);
  // 如果新元素是可编辑的，让它获得焦点
  focusDom.focus();
};

/**
 * 视频混剪预览 模拟数据
 */

export const filterArr = ref([
  {
    title: "视频类型",
    id: 1,
    items: [
      {
        id: 3,
        name: "全部",
        num: 0,
        type: "videoType",
      },
      {
        id: 2,
        name: "极低重复率视频",
        num: 0,
        type: "videoType",
      },
      {
        id: 1,
        name: "低重复率视频",
        num: 0,
        type: "videoType",
      },
      {
        id: 0,
        name: "普通视频",
        num: 0,
        type: "videoType",
      },
    ],
  },
  {
    title: "视频时长",
    id: 2,
    items: [
      {
        id: 0,
        name: "全部",
        type: "time",
      },
      {
        id: "0-20",
        name: "0s-20s",
        type: "time",
      },
      {
        id: "21-40",
        name: "21s-40s",
        type: "time",
      },
      {
        id: "41-60",
        name: "41s-60s",
        type: "time",
      },
      {
        id: "61-90",
        name: "61s-90s",
        type: "time",
      },
      {
        id: "91-120",
        name: "91s-120s",
        type: "time",
      },
      {
        id: "121-999999999",
        name: ">=121s",
        type: "time",
      },
    ],
  },
]);

/**
 * 视频截取视频帧, 生成cavans
 * @param {
 *  videoElement:视频元素id,
 *  canvasElement: canvas元素id,
 *  videoLen:视频时长,
 *  videoUrl:视频链接,
 *  interval:截取间隔,
 *  resolveArr:存放截取数据的ref 数组
 * }
 */
export const splitVideo = async (data, resolveArr) => {
  const { videoId, canvasId, videoLen, videoUrl, interval } = data;
  // 获取元素
  const videoElement = document.querySelector(videoId);
  // const videoUrl = 'https://cos.kuaijingai.com/upload/work_ai/20240305/65e6f4034cd8937599.mp4'
  videoElement.src = videoUrl; // 赋值视频链接
  const canvasElement = document.querySelector(canvasId);
  const ctx = canvasElement.getContext("2d");
  // 开始处理每个时间段 等待视频元数据加载完成
  await new Promise((resolve) => {
    videoElement.addEventListener("loadedmetadata", resolve, { once: true });
  });

  // 设置canvas的大小缩放
  canvasElement.width = videoElement.videoWidth * 0.8;
  canvasElement.height = videoElement.videoHeight * 0.8;
  // 遍历时间段并截图
  let forTime = Math.ceil(videoLen / interval).toFixed(0); // 向上取整
  console.log(forTime, "总次数");
  for (let i = 0; i < forTime; i++) {
    // 计算当前帧的时间
    let currentTime = interval * i;
    // console.log(currentTime, '当前帧');
    if (currentTime > videoLen) {
      currentTime = videoLen;
      // console.log(currentTime, '最后一帧');
    }
    // 设置视频的当前播放时间
    videoElement.currentTime = currentTime;
    // 等待视频跳转到该时间点
    await new Promise((resolve) => {
      videoElement.addEventListener("seeked", resolve, { once: true });
    });
    // 绘制当前视频帧到canvas上
    ctx.drawImage(
      videoElement,
      0,
      0,
      canvasElement.width,
      canvasElement.height
    );
    // 将当前帧转换为base64编码的图片
    const base64ImageData = canvasElement.toDataURL("image/jpeg", 1);
    resolveArr.push({
      ruler: currentTime === 0,
      src: base64ImageData,
      time: currentTime,
      text: "",
    });

    if (currentTime === videoLen) break;
  }

  // 此处已完成截取
  console.log(resolveArr, "截取数据");
};

/**
 * @param {
 *  videoId:视频元素id,
 *  canvasId: canvas元素id,
 *  videoUrl:视频链接,
 *  maxFrameHeight:每个帧画面最大高度,
 *  canvasWidth: 画布宽度,
 * }
 */
export const splitAndDrawVideoFrames = async (data) => {
  const { videoId, canvasId, videoUrl, maxFrameHeight, canvasWidth } = data;

  const videoElement = document.querySelector(videoId);
  videoElement.crossOrigin = "Anonymous";
  videoElement.src = videoUrl + "?v=" + new Date().valueOf();

  // 等待视频的元数据载入完成
  await new Promise((resolve) =>
    videoElement.addEventListener("loadedmetadata", resolve, { once: true })
  );

  const videoDuration = videoElement.duration; // 获取视频总时长
  const frameRate = videoElement.videoWidth / videoElement.videoHeight; // 获取视频帧宽高比
  const frameWidth = frameRate * maxFrameHeight; // 计算帧宽度
  const totalFrames = Math.floor(canvasWidth / frameWidth); // 计算总帧数以铺满总宽度
  const interval = videoDuration / totalFrames; // 根据总帧数计算时间间隔

  const canvasElement = document.querySelector(canvasId);
  const ctx = canvasElement.getContext("2d");

  // 设置Canvas的大小
  canvasElement.width = canvasWidth;
  canvasElement.height = maxFrameHeight; // 只绘制一行

  for (let i = 0; i < totalFrames; i++) {
    const currentTime = interval * i;

    videoElement.currentTime = currentTime;
    await new Promise((resolve) =>
      videoElement.addEventListener("seeked", resolve, { once: true })
    );

    const posX = i * frameWidth;

    ctx.drawImage(videoElement, posX, 0, frameWidth, maxFrameHeight);
  }

  console.log("Finished drawing frames");
};

export const millisToHoursMinutesSeconds = (millis) => {
  let seconds = Math.floor(millis / 1000);
  let minutes = Math.floor(seconds / 60);
  let hours = Math.floor(minutes / 60);

  seconds = seconds % 60;
  minutes = minutes % 60;

  // 使用padStart来确保数字至少为两位数，不足补0
  hours = hours.toString().padStart(2, "0");
  minutes = minutes.toString().padStart(2, "0");
  seconds = seconds.toString().padStart(2, "0");
  return `${hours}:${minutes}:${seconds}`;
};

// 计算可拖拽区域的宽高比例
export const calculateDraggableArea = (userWidth, userHeight) => {
  // debugger
  const containerWidth = phoneWidth;
  const containerHeight = phoneHeight;

  // 计算缩放比例，这次我们用容器宽高除以用户宽高，以获取缩小比例
  const widthScale = containerWidth / userWidth;
  const heightScale = containerHeight / userHeight;

  // 选择较小的缩放比例以保持内容比例
  const scale = Math.min(widthScale, heightScale);

  // 使用缩放后的用户输入宽高作为可拖拽区域的宽高
  // 这会确保无论用户输入的分辨率如何，可拖拽区域都不会超出容器
  const draggableWidth = userWidth * scale;
  const draggableHeight = userHeight * scale;

  // 返回计算结果，包括可拖拽区域的宽高和缩放比例
  return { draggableWidth, draggableHeight, scale, widthScale, heightScale };
};

// 获取目标分辨率下的字体大小
export const getScaleFontSIze = (fontsize) => {
  // 当前分辨率的宽度和目标分辨率的宽度
  const currentHeight = sizeData.value.draggableHeight; // 当前容器分辨率的高度
  const targetHeight = store.state.shotstack.VideoMashup.height; // 目标分辨率的高度

  // 计算比例
  const scale = currentHeight / targetHeight;

  // 计算当前分辨率下的字体大小
  return fontsize * scale;
};

// 比例变化后获取内部文本的变化后的比例位置
export const calculateNewPosition = (
  originalX,
  originalY,
  oldSizeData,
  sizeData
) => {
  // 计算子元素的原始位置比例
  const positionRatioX = originalX / oldSizeData.draggableWidth;
  const positionRatioY = originalY / oldSizeData.draggableHeight;

  // 计算子元素在新容器中应有的位置
  const newElementX = sizeData.draggableWidth * positionRatioX;
  const newElementY = sizeData.draggableHeight * positionRatioY;
  // // 计算缩放后的新位置

  const newPositionX = Math.round(newElementX);
  const newPositionY = Math.round(newElementY);
  // 返回新的位置
  return { newPositionX, newPositionY };
};

// 计算新增的项, 初始的文本位置比例
export const sizeData = computed(() => {
  return calculateDraggableArea(
    store.state.shotstack.VideoMashup.width || 1080,
    store.state.shotstack.VideoMashup.height || 1920
  );
});

// 请求回来数据后, 进行比例换算, 换算回手机展示的比例
/**
 *
 * @param {} height
 * @param {*} width
 * @returns
 */
export const resetXY = (height, width) => {
  // 已有的计算可拖拽区域
  const { widthScale, heightScale } = calculateDraggableArea(
    phoneWidth,
    phoneHeight
  );
  // 计算当前宽高与目标分辨率的比例
  const targetScaleWidth = width / phoneWidth;
  const targetScaleHeight = height / phoneHeight;
  // 计算最终应用于元素的缩放比例
  const scaleWidth = targetScaleWidth * widthScale;
  const scaleHeight = targetScaleHeight * widthScale;

  // 此处返回的是缩放比例倍率, x和y除以缩放比例即为回显的正确比例
  return {
    scaleWidth,
    scaleHeight,
  };
};

// 提交数据时, 还原x和y的位置信息
export const getScalePosition = (data) => {
  // debugger
  // 已有的计算可拖拽区域
  const { widthScale, heightScale } = calculateDraggableArea(
    sizeData.value.draggableWidth,
    sizeData.value.draggableHeight
  );
  // 计算当前宽高与目标分辨率的比例
  const targetScaleWidth = data.width / phoneWidth;
  const targetScaleHeight = data.height / phoneHeight;
  // 计算最终应用于元素的缩放比例
  const finalScaleWidth = targetScaleWidth * widthScale;
  // const finalScaleHeight = targetScaleHeight * heightScale;
  const finalScaleHeight = targetScaleHeight * widthScale;

  // 此处返回的是缩放比例倍率, x和y乘以缩放比例即为最终提交给后端的位置
  return {
    finalScaleWidth,
    finalScaleHeight,
  };
};

// 处理小数点后面很多位的情况
export const numSplit = (num) => {
  return Math.floor(num * 100) / 100;
};

// 转换x和y为提交的数据
export const getSubmitData = () => {
  const submitData = JSON.parse(
    JSON.stringify(store.state.shotstack.VideoMashup)
  );
  // 提交数据之前将比例换算回来, 用于提交等比例数据

  // 旧的小比例
  const oldScaleData = resetXY(submitData.showHeight, submitData.showWidth);

  // 大比例
  const resetScaleData = resetXY(submitData.height, submitData.width);

  console.log(oldScaleData, "回显的比例123123");

  // 提交给后端的原始比例
  // submitData.width = submitData.width * 4
  // submitData.height = submitData.height * 4
  const scaleData = getScalePosition({
    width: submitData.width,
    height: submitData.height,
  });

  console.log(scaleData, "最后提交计算的比例");
  submitData.resource_data.forEach((ele) => {
    ele.tts_config.forEach((i) => {
      delete i.risk_data;
      i.subtitle.forEach((item) => {
        item.x = numSplit(item.x * 4 * oldScaleData.scaleWidth);
        // item.rightX = numSplit(item.rightX * 4 * oldScaleData.scaleWidth);
        // item.showX = numSplit(item.showX * 4 * oldScaleData.scaleWidth);
        item.y = numSplit(item.y * 4 * oldScaleData.scaleWidth);
        item.font_size = numSplit(
          (+item.font_size * resetScaleData.scaleWidth) /
            oldScaleData.scaleWidth
        );
      });
    });
    ele.text_config.forEach((item) => {
      delete item.risk_data_text_config;
      item.x = numSplit(item.x * 4 * oldScaleData.scaleWidth);
      item.y = numSplit(item.y * 4 * oldScaleData.scaleWidth);
      // item.rightX = numSplit(item.rightX * 4 * oldScaleData.scaleWidth);
      // item.showX = numSplit(item.showX * 4 * oldScaleData.scaleWidth);
      item.font_size = numSplit(
        (+item.font_size * resetScaleData.scaleWidth) / oldScaleData.scaleWidth
      );
    });
    // 过滤正在生成的素材
    ele.material_list = ele.material_list.filter((ele) => {
      return ele.material_url != "";
    });
  });

  submitData.global_text_config.configs.forEach((ele) => {
    ele.forEach((item) => {
      item.x = numSplit(item.x * 4 * oldScaleData.scaleWidth);
      item.y = numSplit(item.y * 4 * oldScaleData.scaleWidth);
      // item.rightX = numSplit(item.rightX * 4 * oldScaleData.scaleWidth);
      // item.showX = numSplit(item.showX * 4 * oldScaleData.scaleWidth);
      item.font_size = numSplit(
        (+item.font_size * resetScaleData.scaleWidth) / oldScaleData.scaleWidth
      );
    });
  });

  submitData.global_tts_config.configs.forEach((ele) => {
    delete ele.risk_data;
    ele.subtitle.forEach((item) => {
      item.x = numSplit(item.x * 4 * oldScaleData.scaleWidth);
      item.y = numSplit(item.y * 4 * oldScaleData.scaleWidth);
      // item.rightX = numSplit(item.rightX * 4 * oldScaleData.scaleWidth);
      // item.showX = numSplit(item.showX * 4 * oldScaleData.scaleWidth);
      item.font_size = numSplit(
        (+item.font_size * resetScaleData.scaleWidth) / oldScaleData.scaleWidth
      );
    });
  });
  return submitData;
};

// 字体列表
const fontList = computed(() => {
  return store.state.shotstack.fontList;
});

// 花字列表
const FlowerArr = computed(() => {
  return store.state.shotstack.FlowerArr;
});

function generateUniqueId() {
  const timestamp = Date.now(); // 获取当前时间戳
  const randomNum = Math.floor(Math.random() * 1000); // 生成一个0到999之间的随机数
  return timestamp * 1000 + randomNum; // 确保随机数不会影响时间戳的唯一性
}

// 获取当前创建项目时间时间
export const getNowTime = () => {
  const currentDateTime = dayjs();
  const currentYear = currentDateTime.year();
  const currentMonth = currentDateTime.month() + 1; // 月份从0开始，需要加1
  const currentDay = currentDateTime.date();
  const currentHour = currentDateTime.hour();
  const currentMinute = currentDateTime.minute();
  const currentSecond = currentDateTime.second();
  // titleText.value = `混剪项目_${currentYear}.${currentMonth}.${currentDay} ${currentHour}:${currentMinute}:${currentSecond}`;
  return `${currentYear}.${currentMonth}.${currentDay} ${currentHour}:${currentMinute}:${currentSecond}`;
};

export function calculateFontSize(
  fontSize,
  targetResolutionHeight,
  targetResolutionWidth
) {
  const aspectRatio = calculateAspectRatio(
    targetResolutionWidth,
    targetResolutionHeight
  );
  // Default resolution height is set to 720, adjust based on actual needs later
  const baseResolutionHeight = (() => {
    switch (aspectRatio) {
      case "9:16":
        return 1080;
      case "16:9":
        return 720;
      case "1:1":
        return 720;
      case "4:3":
        return 720;
      case "4:5":
        return 720;
      default:
        return targetResolutionHeight;
    }
  })();

  return Math.floor(fontSize * (targetResolutionHeight / baseResolutionHeight));
}
// 根据比例计算 字体大小 辅助函数
function calculateAspectRatio(width, height) {
  const gcd = (w, h) => (h ? gcd(h, w % h) : w);
  const simplifiedWidth = width / gcd(width, height);
  const simplifiedHeight = height / gcd(width, height);
  return `${simplifiedWidth}:${simplifiedHeight}`;
}

// 创建脚本模拟数据
export const createScriptData = () => {
  let defaultVoiceData =
    store.state.shotstack.defaultVoiceData ||
    localStorage.getItem("defaultVoiceData");
  return {
    title: "", // 脚本标题
    script_type: "user", // 脚本创建类型：user-表示用户创建,org-表示机构创建,本接口固定传：user
    platform: 1, // 适用平台（0-第三方平台，1-自有平台），不传值默认记为0
    subtitle_status: "on", // 场景音频字幕开关:on-开启，off-关闭 (platform为1时，固定传on)
    script_line_tag_id: 0, // 标签ID(无需求直接传0)
    // 全局音频配置
    audio_config: {
      // platorm为1时有效，为0时可不填
      name: defaultVoiceData.name || "智莲", // 音色名称
      human_style: "通用女声", // 音色介绍
      img:
        defaultVoiceData.img ||
        "https://local.kuaijingai.com/public_web/static/images/workAi/voice/icon-women.png", // 音色头像
      voice_type: defaultVoiceData.voice_id || 101034, // 音色id
      volume: 10, // 音量
      speed: 1.2, // 语速
      emotion_category: "neutral", // 情感类型
      emotion_intensity: 100, // 情感程度
      start_time: 0, //开始时间
      audio_url:
        "https://bailing-1305744786.cos.ap-nanjing.myqcloud.com/upload/work_ai/mp3/20240509/663ccae07ba1895854.mp3", //音色选择音频地址
    },
    subtitle_config: {}, // 字幕设置(platform为1时，可以直接空数组),
    script_scenes: [
      // 脚本场景内容
      {
        name: "黄金三秒", //分镜名称
        seconds_type: 0,
        seconds: 5,
        remark: "", //分镜描述
        audio_config: {
          // platorm为1时有效，为0时可不填
          name: defaultVoiceData.name || "智莲", // 音色名称
          human_style: "", // 音色介绍
          img:
            defaultVoiceData.img ||
            "https://local.kuaijingai.com/public_web/static/images/workAi/voice/icon-women.png", // 音色头像
          voice_type: defaultVoiceData.voice_id || 101034, // 音色id
          volume: 10, // 音量
          speed: 1.2, // 语速
          emotion_category: "", // 情感类型
          emotion_intensity: "", // 情感程度
          start_time: 0, //开始时间
          open_global: true, //是否打开全局
          audio_url:
            "https://bailing-1305744786.cos.ap-nanjing.myqcloud.com/upload/work_ai/mp3/20240509/663ccae07ba1895854.mp3", //音色选择音频地址
        },

        line_audio: [
          // platorm为1时，只有一组字幕
          {
            elements: [
              // 多行字幕，每行字幕是一个回车
              [
                {
                  type: "text", // type,text-文字，mute-静音,pause-停顿,phoneme-修改发音，number-数字读音
                  text: "",
                },
              ],
              [
                {
                  type: "text",
                  text: "",
                },
              ],
            ],
            content: "", // 生成音频的文本
            conver_to_audio: "off", // 是否已转换音频
            duration_text: "", // 音频时长格式化
            duration: 0, // 音频时长
            audio_url: "", // 生成的视听音频
          },
        ], //台词文案

        remark_example_url: [], // 分镜描述图片
        example_url: [], // 已拍摄片段
      },
      {
        name: "优势呈现", //分镜名称
        seconds_type: 0,
        seconds: 5,
        remark: "", //分镜描述
        audio_config: {
          // platorm为1时有效，为0时可不填
          name: defaultVoiceData.name || "智莲", // 音色名称
          human_style: "", // 音色介绍
          img:
            defaultVoiceData.img ||
            "https://local.kuaijingai.com/public_web/static/images/workAi/voice/icon-women.png", // 音色头像
          voice_type: defaultVoiceData.voice_id || 101034, // 音色id
          volume: 10, // 音量
          speed: 1.2, // 语速
          emotion_category: "", // 情感类型
          emotion_intensity: "", // 情感程度
          start_time: 0, //开始时间
          open_global: true, //是否打开全局
          audio_url:
            "https://bailing-1305744786.cos.ap-nanjing.myqcloud.com/upload/work_ai/mp3/20240509/663ccae07ba1895854.mp3", //音色选择音频地址
        },

        line_audio: [
          // platorm为1时，只有一组字幕
          {
            elements: [
              // 多行字幕，每行字幕是一个回车
              [
                {
                  type: "text", // type,text-文字，mute-静音,pause-停顿,phoneme-修改发音，number-数字读音
                  text: "",
                },
              ],
              [
                {
                  type: "text",
                  text: "",
                },
              ],
            ],
            content: "", // 生成音频的文本
            conver_to_audio: "off", // 是否已转换音频
            duration_text: "", // 音频时长格式化
            duration: 0, // 音频时长
            audio_url: "", // 生成的视听音频
          },
        ], //台词文案
        remark_example_url: [], // 分镜描述图片
        example_url: [], // 已拍摄片段
      },
      {
        name: "结尾行动号召", //分镜名称
        seconds_type: 0,
        seconds: 5,
        remark: "", //分镜描述
        audio_config: {
          // platorm为1时有效，为0时可不填
          name: defaultVoiceData.name || "智莲", // 音色名称
          human_style: "", // 音色介绍
          img:
            defaultVoiceData.img ||
            "https://local.kuaijingai.com/public_web/static/images/workAi/voice/icon-women.png", // 音色头像
          voice_type: defaultVoiceData.voice_id || 101034, // 音色id
          volume: 10, // 音量
          speed: 1.2, // 语速
          emotion_category: "", // 情感类型
          emotion_intensity: "", // 情感程度
          start_time: 0, //开始时间
          open_global: true, //是否打开全局
          audio_url:
            "https://bailing-1305744786.cos.ap-nanjing.myqcloud.com/upload/work_ai/mp3/20240509/663ccae07ba1895854.mp3", //音色选择音频地址
        },

        line_audio: [
          // platorm为1时，只有一组字幕
          {
            elements: [
              // 多行字幕，每行字幕是一个回车
              [
                {
                  type: "text", // type,text-文字，mute-静音,pause-停顿,phoneme-修改发音，number-数字读音
                  text: "",
                },
              ],
              [
                {
                  type: "text",
                  text: "",
                },
              ],
            ],
            content: "", // 生成音频的文本
            conver_to_audio: "off", // 是否已转换音频
            duration_text: "", // 音频时长格式化
            duration: 0, // 音频时长
            audio_url: "", // 生成的视听音频
          },
        ], //台词文案
        remark_example_url: [], // 分镜描述图片
        example_url: [], // 已拍摄片段
      },
    ],
    org_id: "1",
    user_token:
      "c09NZndldSt1R3k0dVBoNkJVZ3d5RnlrRFptdUJzckdJc2hBQ0w5ekdXNWtiM0plTWZ2ZnFWTTBwUHNQb3QzclZRS1ZEK29rMEIxV0hTTmZPTzh2M0NmUlZYaWJyQU13VzRmZXRzK1JJZzQ3U3FFQUUyVEhvUHMrOTVPMkVDNGk5ZXU1UFpjNG1WWEp6c2hEaHVCQ0RIbCsxaXlhTElKMVVaaFAyOU1qcDZGTU1SZUxudFh2STFHNXFxbkRSQVBXRkVaTzEwM2crSVQrb0lkMWFtRGd2dnNEYVAxczIrUWNlL3ZBeFRWM2gvQmE4bldVK3RRczhna29SUEZhMTV6cjR4U3J3QkVtZDkrTys4WjMyQXJSYzZSVC9hb2l3a2M5bm95YmpDaGJLclFSYU82VzNxQ0pKSW9VVHl5MHFtVlZ6NEtxZ3krUVBMdHdlbEtIaWcyRXVRPT0=",
    cur_env: "pc",
    team_id: "1",
  };
};
// 创建脚本列表模拟数据
export const baseScriptScenesItem = () => {
  let defaultVoiceData =
    store.state.shotstack.defaultVoiceData ||
    localStorage.getItem("defaultVoiceData");
  return {
    name: "", //分镜名称
    seconds_type: 0,
    seconds: 5,
    remark: "", //分镜描述
    audio_config: {
      // platorm为1时有效，为0时可不填
      name: defaultVoiceData.name || "智莲", // 音色名称
      human_style: "", // 音色介绍
      img:
        defaultVoiceData.img ||
        "https://local.kuaijingai.com/public_web/static/images/workAi/voice/icon-women.png", // 音色头像
      voice_type: defaultVoiceData.voice_id || 101034, // 音色id
      volume: 10, // 音量
      speed: 1.2, // 语速
      emotion_category: "neutral", // 情感类型
      emotion_intensity: 50, // 情感程度
      start_time: 0, //开始时间
      open_global: true, //是否打开全局
      audio_url:
        "https://bailing-1305744786.cos.ap-nanjing.myqcloud.com/upload/work_ai/mp3/20240509/663ccae07ba1895854.mp3", //音色选择音频地址
    },

    line_audio: [
      // platorm为1时，只有一组字幕
      {
        elements: [
          // 多行字幕，每行字幕是一个回车
          [
            {
              type: "text", // type,text-文字，mute-静音,pause-停顿,phoneme-修改发音，number-数字读音
              text: "",
            },
          ],
          [
            {
              type: "text",
              text: "",
            },
          ],
        ],
        content: "", // 生成音频的文本
        conver_to_audio: "off", // 是否已转换音频
        duration_text: "", // 音频时长格式化
        duration: 0, // 音频时长
        audio_url: "", // 生成的视听音频
      },
    ], //台词文案
    remark_example_url: [], // 分镜描述图片
    example_url: [], // 已拍摄片段
  };
};

// 获取ssml 后端所需要的结构, 接受富文本的html
export const getSsml = (html) => {
  const output = html
    .replace(/<speak subid="[^"]+">/g, "<speak>") // 去除 subid 属性
    .replace(/text="[^"]+"/g, "") // 去除 text 属性
    .replace(/<cancelread[^>]*><\/cancelread>/g, ""); // 完全去除 cancelread 标签及其内容
  console.log(output, "输出的数据");
  return output;
};

// 时间格式转换
export function convertToDateOnly(isoString) {
  // 创建一个新的 Date 对象
  const date = new Date(isoString);

  // 获取年份、月份和日期，并格式化为 YYYY-MM-DD
  const year = date.getUTCFullYear();
  const month = String(date.getUTCMonth() + 1).padStart(2, "0"); // 月份从 0 开始，所以需要 +1
  const day = String(date.getUTCDate()).padStart(2, "0");

  // 拼接成 YYYY-MM-DD 格式
  return `${year}-${month}-${day}`;
}

// 计算手机组件中 字幕宽度
export const measureTextWithSpan = (element, text) => {
  // 创建一个临时的 span 元素
  // debugger
  const tempSpan = document.createElement("p");
  // visibility: hidden;
  tempSpan.style.cssText = `
    position: absolute;
    white-space: pre-wrap;
    font-size: ${getComputedStyle(element)["font-size"]};
    font-style: ${getComputedStyle(element)["font-style"]};
    font-weight: ${getComputedStyle(element)["font-weight"]};
    line-height: ${getComputedStyle(element)["line-height"]};
    font-family: ${getComputedStyle(element)["font-family"]};
    word-wrap: ${getComputedStyle(element)["word-wrap"]};
    word-break: ${getComputedStyle(element).wordBreak};
    text-align: ${getComputedStyle(element).textAlign};
    padding:${getComputedStyle(element).padding};
  `;
  tempSpan.textContent = text;

  // 将 span 添加到 body 中以便计算样式
  document.body.appendChild(tempSpan);

  // 获取 span 的宽度和高度
  // 补充误差
  const width = tempSpan.offsetWidth + 3;
  const height = tempSpan.offsetHeight;

  // 移除 span
  document.body.removeChild(tempSpan);

  return { width, height };
};

// 颜色进行rgba转换
export const hexToRgba = (hex, alpha) => {
  // 移除可能存在的 # 符号
  if (hex) {
    hex = hex.replace("#", "");
    // 将十六进制颜色代码转换为 RGB 值
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);

    // 返回 rgba 格式的颜色字符串
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  } else {
    return "transparent";
  }
};

// 获取文本的预计时长 所需的参数: 文本 + 停顿时间
export const processText = (input) => {
  const parser = new DOMParser();
  const doc = parser.parseFromString(input, "application/xml");
  const breakTags = doc.getElementsByTagName("break");
  let totalTime = 0;

  // 计算所有 break 标签的 time 值总和
  for (let i = 0; i < breakTags.length; i++) {
    const timeAttr = breakTags[i].getAttribute("time");
    if (timeAttr) {
      const timeInMs = parseInt(timeAttr.replace("ms", ""), 10);
      totalTime += timeInMs;
    }
  }
  // 总共的文本总和
  let resultText = "";
  // 获取根节点
  const rootNode = doc.documentElement;
  // 获取根节点的文本内容
  resultText = rootNode.textContent;
  const data = {
    totalTime,
    resultText,
  };
  console.log(data, "resultTextresultTextresultText");
  return data;
};

// 获取预估的字幕组时间
export const estimateAudioDuration = (text) => {
  // 计算中文字符的数量
  const chineseCharCount = (text.match(/[\u4e00-\u9fff]/g) || []).length;
  // 计算非中文字符的数量
  const nonChineseCount = text.replace(/[\u4e00-\u9fff]/g, "").length;
  // 每个中文字符的发音时间（秒）
  const chineseCharDuration = 0.2;
  // 每个非中文字符的发音时间（秒）
  const nonChineseDuration = 0.2;
  // 计算总发音时间
  let totalDuration =
    chineseCharCount * chineseCharDuration +
    nonChineseCount * nonChineseDuration;
  // 设置最小时长为1秒，当文本总长度不足5个字符或单词时
  if (totalDuration < 1) {
    totalDuration = 1;
  }
  return Math.floor(totalDuration);
};

/**
 *
 * @param {拆解的文本} text
 * @param {敏感词数组} keywords
 * @keyword {是否是敏感词}
 * @returns {text: any; keyword: boolean;}
 */
export const splitTextByKeywords = (text, keywords) => {
  // 创建一个正则表达式，用于匹配所有关键字
  const regex = new RegExp(`(${keywords.join("|")})`, "g");

  // 使用正则表达式将文本拆分成数组
  const parts = [];
  let match;
  let lastIndex = 0;

  while ((match = regex.exec(text)) !== null) {
    if (match.index > lastIndex) {
      parts.push({ text: text.slice(lastIndex, match.index), keyword: false });
    }
    parts.push({ text: match[0], keyword: true });
    lastIndex = regex.lastIndex;
  }

  if (lastIndex < text.length) {
    parts.push({ text: text.slice(lastIndex), keyword: false });
  }

  return parts;
};

// 富文本敏感词替换, 暂时没用
export const SensitiveWordsReplace = (jsonData) => {
  const keywords = ["关键1", "关键2", "关键3"];
  // const keywords = [];

  // 如果有敏感词
  if (keywords.length) {
    const regex = new RegExp(`(${keywords.join("|")})`, "g");
    jsonData.content.forEach((ele) => {
      console.log(ele, "每一项");
      Array.isArray(ele.content) &&
        ele.content.length &&
        ele.content.forEach((item, index) => {
          if (item.type == "text" && item.text && !item.marks) {
            // 判断是否有关键词, 有关键词的话, 将文本依照关键词进行拆分, 普通的地方用普通文本, 关键词的地方使用paragraph标签
            // 检测文本是否包含关键词
            const hasKeyword = regex.test(item.text);
            if (hasKeyword) {
              // debugger
              // 包含关键字, 将文本按照关键字进行拆分
              const splitArr = splitTextByKeywords(item.text, keywords);
              if (Array.isArray(splitArr) && splitArr.length) {
                const splitDom = splitArr.map((ele) => {
                  // 是关键字
                  if (ele.keyword) {
                    return {
                      type: "text",
                      marks: [
                        {
                          type: "textStyle",
                          attrs: {
                            color: "rgb(149, 141, 241)",
                          },
                        },
                      ],
                      text: ele.text,
                      keyword: true,
                    };
                  } else {
                    return {
                      type: "text",
                      text: ele.text,
                    };
                  }
                });
                ele.content.splice(index, 1, ...splitDom);
              }
            }
          } else {
            // 判断是否符合关键词的标准, 不再是关键词的时候,将它变为普通文本
            const hasKeyword = keywords.some((ele) => ele == item.text);
            if (!hasKeyword) {
              // 没有找到全等的关键词 1.用户在前后增加了文字,导致不全等. 2.用户在中间输入了文字,导致该关键词标注失效
              const hasKeyword = regex.test(item.text);
              // 已经没有关键词了
              if (!hasKeyword) {
                ele.content.splice(index, 1, {
                  type: "text",
                  text: item.text,
                });
              } else {
                // 需要切除关键词前后多余的文本
                // 包含关键字, 将文本按照关键字进行拆分
                const splitArr = splitTextByKeywords(item.text, keywords);
                if (Array.isArray(splitArr) && splitArr.length) {
                  const splitDom = splitArr.map((ele) => {
                    // 是关键字
                    if (ele.keyword) {
                      return {
                        type: "text",
                        marks: [
                          {
                            type: "textStyle",
                            attrs: {
                              color: "rgb(149, 141, 241)",
                            },
                          },
                        ],
                        text: ele.text,
                        keyword: true,
                      };
                    } else {
                      return {
                        type: "text",
                        text: ele.text,
                      };
                    }
                  });
                  ele.content.splice(index, 1, ...splitDom);
                }
              }
            }
          }
        });
    });
  } else {
    // 关键词列表不存在, 将所有的关键词标注, 设置为普通文本
    jsonData.content.forEach((ele) => {
      Array.isArray(ele.content) &&
        ele.content.length &&
        ele.content.forEach((item, index) => {
          if (!!item?.marks) {
            ele.content.splice(index, 1, {
              type: "text",
              text: item.text,
            });
          }
        });
    });
  }

  return jsonData;
};

// 风险词基础数据
export const risk_types_baseData = [
  {
    name: "高风险",
    id: "high_risk",
    bgcolor: "#ffb6b6",
    textcolor: "#FF4D4F",
    // text- 风险文案
    // tags- 触发的风险词
    risk_text: [], // 风险文案数组
  },
  {
    name: "中风险",
    id: "medium_risk",
    textcolor: "#FAAD14",
    bgcolor: "#ffe8b7",
    risk_text: [], // 风险文案数组
  },
  {
    name: "低风险",
    id: "low_risk",
    bgcolor: "#cdfeb6",
    textcolor: "#55C51F",
    risk_text: [], // 风险文案数组
  },
  {
    name: "自定义风险词",
    id: "custom_risk",
    bgcolor: "#bcb8fe",
    textcolor: "#5C53FF",
    risk_text: [], // 风险文案数组
  },
];

// 自动获取焦点指令
export const autoFocus = {
  mounted(el, binding) {
    // if (binding.value) {
    nextTick(() => {
      el.focus();
    });
    // }
  },
  updated(el, binding) {
    // if (binding.value) {
    nextTick(() => {
      el.focus();
    });
    // }
  },
};

// 文本按照标点符号切割的方法
export function splitTextAndRemoveCommas(text) {
  // 使用正则表达式进行拆分，匹配句号、问号（包括大小写）、逗号和感叹号
  const sentences = text.split(/(?<=[。？！!,，])/i);

  // 遍历数组，去除每个元素中的逗号和句号
  const result = sentences.map((sentence) => sentence.replace(/[，,。]/g, ""));

  // 过滤掉可能的空字符串
  const textArr = result.filter((sentence) => sentence.trim() !== "");

  return textArr;
}

// 添加换行符的方法
export function addNewlineAfterPunctuation(text) {
  // 匹配指定的标点符号并在其后面添加换行符
  const replaceText = text.replace(/([。？！!,，])(?!$)/g, "$1\n");
  // 返回去除句号逗号的结果
  const result = replaceText.replace(/[，,。]/g, "");
  // 如果末尾是换行符，则去除末尾的换行符
  return result.endsWith("\n") ? result.slice(0, -1) : result;
}

// 获取所有视频组中的, 每个tts的每个subtitle的音频
export const getAllTemplateAudio = async (templateList) => {
  console.log(templateList, "接收到即将获取音频的数据乐乐乐乐乐");
  return new Promise(async (resolve, reject) => {
    message.loading("字幕语音转换中...", 0);
    // try {
    // 外层遍历每个视频组
    for (let item of templateList) {
      // 所有手动输入的 tts项, 内部的每一项 Subtitle 都需要获取音频
      const target_tts = item.tts_config.filter((ele) => ele.tab_id == "text");
      for (let tts_item of target_tts) {
        await getItemTts_subtitle_audioData(tts_item, { mexid_all: true });
      }
    }
    message.destroy();
    resolve(templateList);
    // } catch (error) {
    //   message.destroy()
    //   reject(error)
    // }
  });
};

// 获取单项的tts音频
export const getItemTts_subtitle_audioData = async (tts_item, params) => {
  // 有文本, 并且没有音频选项的 才需要获取音频
  const textAndSubtitleId = tts_item.subtitle
    .filter(
      (sub) => !!sub.text.trim() && sub.text.trim() !== "\n" && !sub.audio_url
    )
    .map((sub) => ({ text: sub.ssml, id: sub.subtitle_id }));
  if (Array.isArray(textAndSubtitleId) && textAndSubtitleId.length >= 1) {
    // 获取音频需要的参数
    const { speed, tone_id, volume, emotion_category, emotion_intensity } =
      tts_item;

    const { mexid_all } = params;
    const requestData = {
      text: textAndSubtitleId,
      speed,
      timbre_id: tone_id,
      volume,
      emotion_category,
      emotion_intensity,
      unique: nanoid(),
    };
    console.log(requestData, "提交的数据requestData");
    // 找到对应的数据, 存放数据

    // 找到对应的数据, 存放数据
    const setVoice = (arr) => {
      tts_item.subtitle.forEach((ele) => {
        const findTarget = arr.find((i) => i.id == ele.subtitle_id);
        if (!!findTarget) {
          ele.audio_url = findTarget.audio;
          ele.duration = findTarget.duration * 1000;
          if(findTarget?.duration_ms && findTarget?.duration_ms > 0){
            ele.duration = findTarget.duration_ms;
          } 
          ele.end_time = ele.duration;
          ele.material_path = findTarget?.material_path || "";
          ele.media_id = findTarget?.oss_media_id || "";
        }
      });
    };

    // 创建一个函数用于延迟
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    try {
      const res = await request.post(
        "/work_ai",
        "/user/shotstack/textToVoice/many",
        { ...requestData, mexid_all }
      );
      console.log(
        res,
        "返回参数如果audio为空，task_id有值，需要用task_id去轮询获取url"
      );

      // 使用新的获取音频接口
      const getItemVoice = async () => {
        const itemVoice = await request.get(
          "/work_ai",
          `/user/shotstack/textToVoice/many/result/${requestData.unique}`
        );
        console.log("单项的轮询结果123", itemVoice);
        if (itemVoice?.code && itemVoice?.code != 1000) {
          throw new Error(itemVoice);
        }
        if (itemVoice?.result?.status) {
          if (itemVoice.result.status == "loading") {
            await delay(2000);
            await getItemVoice();
            return;
          }
          if (itemVoice.result.status == "error") {
            return message.error("音频获取失败!");
          }
        } else {
          console.log("itemVoice?.result 有数据啦", itemVoice?.result);
          setVoice(itemVoice?.result);
        }
      };

      await getItemVoice();

      // 父项 添加总时长
      if (tts_item.subtitle.length) {
        const allTime = tts_item.subtitle.reduce(
          (all, item) => +all + +item.duration,
          0
        );
        tts_item.duration = +allTime;
      }
    } catch (error) {
      message.destroy();
      nextTick(() => {
        message.error("字幕语音转换失败,请重试!");
      });
    }
  }
};

// ai写作助手, 获取全局字幕配音
export const getGlobalSubtitleAudio = async (tts_data) => {
  return new Promise(async (resolve, reject) => {
    message.loading("字幕语音转换中...", 0);
    try {
      for (let tts_item of tts_data) {
        // 有文本, 并且没有音频选项的 才需要获取音频
        await getItemTts_subtitle_audioData(tts_item, { mexid_all: true });
      }

      message.destroy();
      resolve(tts_data);
    } catch (error) {
      message.destroy();
      nextTick(() => {
        message.error("字幕语音转换失败,请重试!");
      });
    }
  });
};

// 小圆点点击试听
export const getAudioData_Set = async (paramsData) => {
  // ssmlData, editItem, target_tts, listenLoding, subTitle, isPlay
  // debugger
  const { mexid_all } = paramsData;
  let data = {
    text: [
      {
        text: paramsData.ssmlData.ssml,
      },
    ],
    speed: paramsData.target_tts.value.speed,
    timbre_id: paramsData.target_tts.value.tone_id || null,
    volume: paramsData.target_tts.value.volume,
    emotion_category: paramsData.target_tts.value.emotion_category,
    emotion_intensity: paramsData.target_tts.value.emotion_intensity,
    unique: nanoid(),
  };
  paramsData.listenLoding.value = true;

  // 找到对应的数据, 存放数据
  const setVoice = (itemVoice) => {
    // 修改找到的对象的音频数据
    paramsData.editItem.value.audio_url = itemVoice[0].audio;
    paramsData.editItem.value.duration = itemVoice[0].duration * 1000;
    if(itemVoice[0]?.duration_ms && itemVoice[0]?.duration_ms > 0){
      paramsData.editItem.value.duration = itemVoice[0].duration_ms;
    } 
    paramsData.editItem.value.end_time = paramsData.editItem.value.duration;
    
    paramsData.editItem.value.material_path = itemVoice[0].material_path;
    paramsData.editItem.value.media_id = itemVoice[0]?.oss_media_id || "";

    // 存储当前数据
    store.commit("INIT_SUBTITLES_DATA", paramsData.subTitle.value);
    // 通知父组件进行播放
    store.commit("SETVIDEOPLAYING_DATA", {
      isPlay: true, // 是否播放
      audio_url: itemVoice[0].audio,
      reset: true, // 是否从头播放
      changeUrl: true, // 是否修改url
    });
    console.log(itemVoice, "听某哥小圆点");
    paramsData.listenLoding.value = false;
    paramsData.isPlay.value = true;
  };

  // 创建一个函数用于延迟
  const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
  try {
    const res = await request.post(
      "/work_ai",
      "/user/shotstack/textToVoice/many",
      { ...data, mexid_all }
    );
    console.log(res.result, "many调用的结果");

    // 使用新的获取音频接口
    const getItemVoice = async () => {
      const itemVoice = await request.get(
        "/work_ai",
        `/user/shotstack/textToVoice/many/result/${data.unique}`
      );
      console.log("单项的轮询结果123", itemVoice);
      if (itemVoice?.code && itemVoice?.code != 1000) {
        throw new Error(itemVoice);
      }
      if (itemVoice?.result?.status) {
        if (itemVoice.result.status == "loading") {
          await delay(2000);
          await getItemVoice();
          return;
        }
        if (itemVoice.result.status == "error") {
          return message.error("音频获取失败!");
        }
      } else {
        console.log("itemVoice?.result 有数据啦", itemVoice?.result);
        setVoice(itemVoice?.result);
      }
    };

    await getItemVoice();
    paramsData.listenLoding.value = false;
    paramsData.isPlay.value = false;
  } catch (error) {
    paramsData.listenLoding.value = false;
    paramsData.isPlay.value = false;
    message.error("字幕语音转换失败,请重试!");
  }
};
